package com.zmj.sy.mom.srv.aps.service;

import cn.hutool.core.collection.CollUtil;
import com.zmj.sy.mom.srv.aps.bean.entity.base.BaseEntity;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.*;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseIdReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseListResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseSelectItemResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseSelectResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.grouprefactor.*;
import com.zmj.sy.mom.srv.aps.mapper.*;
import com.zmj.sy.mom.srv.aps.utils.MkBeanUtils;
import com.zmj.sy.mom.srv.aps.utils.SyExceptionUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
public class GroupRefactorService {

    private final GroupMapper groupMapper;
    private final StationMapper stationMapper;
    private final PhaseGroupMapper phaseGroupMapper;
    private final PhaseMapper phaseMapper;
    private final StationWeekdaySchemeMapper stationWeekdaySchemeMapper;
    private final ShiftTypeMapper shiftTypeMapper;
    private final FactoryMapper factoryMapper;

    @Transactional(readOnly = true)
    public List<GroupRefactGroupTreeResVo> groupTree() {
        String splitStr = "$$$";

        List<GroupRefactGroupTreeResVo> resVo = new ArrayList<>();

        List<Factory> factoryList = factoryMapper.lambdaQuery().list();
        Map<Integer, Factory> factoryMap = factoryList.stream().collect(Collectors.toMap(BaseEntity::getId, e -> e));

        List<GroupRefactGroupTreeResVo> collect4 = factoryList.stream()
                .map(e -> {
                    GroupRefactGroupTreeResVo r = new GroupRefactGroupTreeResVo();
                    r.setType(e.getType());
                    r.setSourceId(e.getId());
                    if(r.getType() > 1){
                        r.setPid((r.getType() - 1) + splitStr + e.getPid() );
                    }
                    r.setCode(e.getMyCode());
                    r.setId(e.getType() + splitStr + e.getId());
                    r.setName(e.getName());
                    return r;
                })
                .sorted(Comparator.comparing(GroupRefactGroupTreeResVo::getCode))
                .collect(Collectors.toList());
        if(CollUtil.isNotEmpty(collect4)){
            resVo.addAll(collect4);
        }



//        GroupRefactGroupTreeResVo root = new GroupRefactGroupTreeResVo();
//        root.setType(4);
//        root.setSourceId(1);
//        root.setId(root.getType() + splitStr + root.getSourceId());
//        root.setName("工作组");
//        resVo.add(root);


        List<Group> groupList = groupMapper.lambdaQuery().eq(Group::getType, 2).list();
        if (CollUtil.isEmpty(groupList)) {
            return resVo;
        }

        List<GroupRefactGroupTreeResVo> collect = groupList.stream()
                .map(e -> {
                    GroupRefactGroupTreeResVo r = new GroupRefactGroupTreeResVo();
                    r.setType(3);
                    r.setSourceId(e.getId());
                    r.setId(r.getType() + splitStr + r.getSourceId());
                    r.setName(e.getName());
                    r.setPid(2 + splitStr + factoryMap.get(e.getLineId()).getId());
                    r.setCode(e.getMyCode());
                    return r;
                })
                .collect(Collectors.toList());
        resVo.addAll(collect);

        List<Integer> groupIdList = groupList.stream().map(BaseEntity::getId).collect(Collectors.toList());
        if(CollUtil.isEmpty(groupIdList)){
            return resVo;
        }
        List<Station> stationList = stationMapper.lambdaQuery().in(Station::getGroupId, groupIdList).list();

        List<String> collect1 = groupList.stream().map(Group::getMyCode).collect(Collectors.toList());
        List<PhaseGroup> phaseGroupList = phaseGroupMapper.lambdaQuery().in(PhaseGroup::getGroupCode, collect1).list();
        Map<String, List<PhaseGroup>> collect2 = phaseGroupList.stream().collect(Collectors.groupingBy(PhaseGroup::getGroupCode));
        Map<Integer, Group> groupMyCodeMap = groupList.stream().collect(Collectors.toMap(Group::getId, Function.identity()));

        for (Station station : stationList) {
            Integer groupId = station.getGroupId();

            GroupRefactGroupTreeResVo r = new GroupRefactGroupTreeResVo();
            r.setType(4);
            r.setSourceId(station.getId());
            r.setId(r.getType() + splitStr + r.getSourceId());
            r.setName(station.getName());
            r.setPid(3 + splitStr + groupId);
            r.setCode(station.getMyCode());
            resVo.add(r);

            Group group = groupMyCodeMap.get(groupId);
            List<PhaseGroup> phaseGroups = collect2.get(group.getMyCode());
            if(CollUtil.isNotEmpty(phaseGroups)){
                for (PhaseGroup phaseGroup : phaseGroups) {
                    GroupRefactGroupTreeResVo r1 = new GroupRefactGroupTreeResVo();
                    r1.setType(5);
                    r1.setSourceId(phaseGroup.getId());
                    r1.setId(r1.getType() + splitStr + r1.getSourceId());
                    r1.setName(phaseGroup.getPhaseCode());
                    r1.setPid(r.getId());
                    r1.setCode(phaseGroup.getPhaseCode());

                    resVo.add(r1);
                }
            }
        }

        return resVo;
    }

    @Transactional(readOnly = true)
    public GroupRefactGroupGetResVo groupGet(BaseIdReqVo reqVo) {
        Group group = groupMapper.selectById(reqVo.getId());
        return MkBeanUtils.copyProperties(group, GroupRefactGroupGetResVo.class);
    }

    public GroupRefactStationGetResVo stationGet(BaseIdReqVo reqVo) {
        Station station = stationMapper.selectById(reqVo.getId());
        GroupRefactStationGetResVo groupRefactStationGetResVo = MkBeanUtils.copyProperties(station, GroupRefactStationGetResVo.class);
        StationWeekdayScheme stationWeekdayScheme = stationWeekdaySchemeMapper.lambdaQuery().eq(StationWeekdayScheme::getStationId, station.getId()).one();
        if(stationWeekdayScheme != null){
            groupRefactStationGetResVo.setWeekdaySchemeId(stationWeekdayScheme.getId());
            groupRefactStationGetResVo.setOrgSchemeId(stationWeekdayScheme.getSchemeId());
        }

        return groupRefactStationGetResVo;
    }

    @Transactional
    public void stationAdd(GroupRefactStationAddReqVo reqVo) {
        Station station = MkBeanUtils.copyProperties(reqVo, Station.class);
        stationMapper.insert(station);

    }

    @Transactional
    public void stationEdit(GroupRefactStationEditReqVo reqVo) {
        Station station = MkBeanUtils.copyProperties(reqVo, Station.class);
        stationMapper.updateById(station);

    }

    @Transactional
    public void stationDel(BaseIdReqVo reqVo) {
        stationMapper.deleteByIdHard(reqVo.getId());
    }

    @Transactional(readOnly = true)
    public GroupRefactPhaseDetailResVo phaseDetail(BaseIdReqVo reqVo) {
        PhaseGroup phaseGroup = phaseGroupMapper.selectById(reqVo.getId());
        return MkBeanUtils.copyProperties(phaseGroup, GroupRefactPhaseDetailResVo.class);
    }

    @Transactional(readOnly = true)
    public GroupRefactPhaseListResVo phaseList(GroupRefactPhaseListReqVo reqVo) {
        Group group = groupMapper.selectById(reqVo.getId());

        List<PhaseGroup> phaseGroupList = phaseGroupMapper.lambdaQuery()
                .eq(PhaseGroup::getGroupCode, group.getMyCode())
                .list();

        List<Phase> phaseList = phaseMapper.lambdaQuery().eq(Phase::getType, 1).list();

        Map<String, Phase> collect2 = phaseList.stream().filter(e -> StringUtils.hasText(e.getMyCode())).collect(Collectors.toMap(e -> e.getMyCode(), Function.identity()));


        GroupRefactPhaseListResVo resVo = new GroupRefactPhaseListResVo();

        List<GroupRefactPhaseListDetailResVo> collect = phaseGroupList.stream()
                .map(e -> {
                    GroupRefactPhaseListDetailResVo rr = new GroupRefactPhaseListDetailResVo();
                    rr.setPhaseId(e.getId());

                    rr.setPhaseName(e.getPhaseCode());
                    Phase phase = collect2.get(e.getPhaseCode());
                    if (phase != null) {
                        rr.setPhaseName(phase.getMyCode() + " - " + phase.getName());

                    }
                    return rr;
                })
                .collect(Collectors.toList());
        resVo.setUsed(collect);

        List<GroupRefactPhaseListDetailResVo> collect1 = phaseList.stream()
                .map(e -> {
                    GroupRefactPhaseListDetailResVo rr = new GroupRefactPhaseListDetailResVo();
                    rr.setPhaseId(e.getId());
                    rr.setPhaseName(e.getMyCode() + " - " + e.getName());
                    return rr;
                })
                .sorted(Comparator.comparing(GroupRefactPhaseListDetailResVo::getPhaseName))
                .collect(Collectors.toList());
        resVo.setAll(collect1);

        return resVo;
    }

    @Transactional
    public void phaseAdd(GroupRefactPhaseAddReqVo reqVo) {
        Group group = groupMapper.selectById(reqVo.getGroupId());
        PhaseGroup phaseGroup = MkBeanUtils.copyProperties(reqVo, PhaseGroup.class);
        Phase phase = phaseMapper.selectById(reqVo.getPhaseId());
        phaseGroup.setGroupCode(group.getMyCode());
        phaseGroup.setPhaseCode(phase.getMyCode());
        phaseGroupMapper.insert(phaseGroup);
    }

    @Transactional
    public void phaseEdit(GroupRefactPhaseEditReqVo reqVo) {
        PhaseGroup phaseGroup = MkBeanUtils.copyProperties(reqVo, PhaseGroup.class);
        phaseGroupMapper.updateById(phaseGroup);
    }

    @Transactional
    public void phaseDel(BaseIdReqVo reqVo) {
        phaseGroupMapper.deleteByIdHard(reqVo.getId());
    }

    @Transactional(readOnly = true)
    public List<GroupRefactShiftTypeSelectResVo> shiftTypeSelect() {
        List<ShiftType> shiftTypeList = shiftTypeMapper.selectList(null);
        return shiftTypeList.stream()
                .map(e->{
                     GroupRefactShiftTypeSelectResVo r = new GroupRefactShiftTypeSelectResVo();
                     r.setId(e.getId());
                     r.setName(e.getName());
                     r.setMyCode(e.getMyCode());
                     r.setStartDate(e.getStartDate());
                     r.setEndDate(e.getEndDate());
                     return r;
                })
                .collect(Collectors.toList());
    }

    @Transactional(readOnly = true)
    public GroupRefactFactoryGetResVo factoryGet(BaseIdReqVo reqVo) {
        Factory factory = factoryMapper.selectById(reqVo.getId());
        return MkBeanUtils.copyProperties(factory, GroupRefactFactoryGetResVo.class);
    }

    @Transactional
    public void factoryEdit(GroupRefactFactoryEditReqVo reqVo) {
        Factory factory = factoryMapper.selectById(reqVo.getId());
        BeanUtils.copyProperties(reqVo, factory, "id");
        factoryMapper.updateById(factory);
    }

    @Transactional(readOnly = true)
    public BaseListResVo<GroupRefactFactoryListResVo> factoryList() {
        List<Factory> factoryList = factoryMapper.lambdaQuery().eq(Factory::getType, 1).list();
        return BaseListResVo.of(factoryList, GroupRefactFactoryListResVo.class);
    }

    @Transactional(readOnly = true)
    public GroupRefactLineGetResVo lineGet(BaseIdReqVo reqVo) {
        Factory factory = factoryMapper.selectById(reqVo.getId());
        return MkBeanUtils.copyProperties(factory, GroupRefactLineGetResVo.class);
    }

    @Transactional
    public void lineEdit(GroupRefactLineEditReqVo reqVo) {
        Factory factory = factoryMapper.selectById(reqVo.getId());
        BeanUtils.copyProperties(reqVo, factory, "id");
        factoryMapper.updateById(factory);
    }

    @Transactional(readOnly = true)
    public BaseListResVo<GroupRefactLineListResVo> lineList(BaseIdReqVo reqVo) {
        List<Factory> factoryList = factoryMapper.lambdaQuery().eq(Factory::getType, 2).eq(Factory::getPid, reqVo.getId()).list();
        return BaseListResVo.of(factoryList, GroupRefactLineListResVo.class);
    }

    @Transactional
    public Integer lineAdd(GroupRefactLineAddReqVo reqVo) {
        Factory factory = MkBeanUtils.copyProperties(reqVo, Factory.class);
        if(reqVo.getPid() == null){
            throw SyExceptionUtils.e("请选择加在哪个工厂下!");
        }
        factory.setType(2);
        factoryMapper.insert(factory);
        return factory.getId();
    }

    @Transactional
    public void lineDelete(BaseIdReqVo reqVo) {

        Integer count = groupMapper.lambdaQuery().eq(Group::getLineId, reqVo.getId()).count();
        if(count > 0){
            throw SyExceptionUtils.e("下面有子节点，无法删除!");
        }

        factoryMapper.deleteByIdHard(reqVo.getId());
    }

    @Transactional(readOnly = true)
    public BaseSelectResVo lineSelect() {
        List<Factory> list = factoryMapper.lambdaQuery().eq(Factory::getType, 2).list();
        return BaseSelectResVo.of(list.stream().map(e -> {
            BaseSelectItemResVo r = new BaseSelectItemResVo();
            r.setValue(e.getId());
            r.setText(e.getName() + "-" + e.getMyCode());
            return r;
        }).collect(Collectors.toList()));

    }
}
